/*-------------------------------------------------------------------------

***************** Modification History ***********************************
   @doc
   @module list.c - Function used to display tables in setup |
   @end

$Log: /SoftPay/SPK2SIM/Source/Utils/list.c $
**************************************************************************

   Copyright (C) 1999 by VeriFone, Inc.

   All rights reserved.  No part of this software may be reproduced,
   transmitted, transcribed, stored in a retrieval system, or translated
   into any language or computer language, in any form or by any means,
   electronic, mechanical, magnetic, optical, chemical, manual or otherwise,
   without the prior written permission of VeriFone, Inc.

---------------------------------------------------------------------------*/
#include <project.h>
#define VSLIST_C

#include <aclconio.h>
#include <stdio.h>
#include <stdlib.h>
#include <applidl.h>

/** /#define DEBUG_VSLIST */
#ifdef DEBUG_VSLIST
#define DEBUG_95
#endif

#include <define.h>
#include <transact.h>
#include <list.h>
#include <cdt.h>
#include <ui.h>
#include <msgfuncs.h>
#include <msg.h>
#include <mem.h>
#include <spdebug.h>
#include <operate.h>
#include <mdlfuncs.h>

/*
 * following prototype here
 * to limit visibility...
 */
extern void vdDisplayFieldNode(void*,void*);

#undef  fValidList
#undef  fValidNode

VS_BOOL fValidList(List* pliList) {
    if (pliList->inListSig != LIST_SIGNATURE) {
        vdDisplayMessageFromFile(INVALID_LIST_MSG, ERROR_MSG);
        return(FALSE);
    }
    return(TRUE);
}

VS_BOOL fValidNode(Node* pndNode) {
    if (pndNode->inNodeSig != NODE_SIGNATURE) {
        vdDisplayMessageFromFile(INVALID_NODE_MSG, ERROR_MSG);
        return(FALSE);
    }
    return(TRUE);
}

int inSelectNode(RecordList* pliListOfChoices,Node** ppndSelectedNode,PFVD_RL_RN pfnDisplayNode) {
    Node* pndCurrentNode = *ppndSelectedNode;
    int inKey = 0;

    // Usha_r2, July 1, commented the following code and added next line
    // FieldList *pflFieldList;
    RecordList* pflRecordList;
    FieldNode* pfnSelectedField;
    FieldDefinition* psrFieldDefinitionPtr;
    long FieldDefSize = REC_SIZEOF(FieldDefinition);

    int inKeyPrev = KEY_a;
    int inKeyNext = KEY_b;
    int inKeySel = KEY_c;
    int inKeyExit = KEY_d;

    if (obDisp.inTerminalType == TERMINAL_OMNI_3200) {
        inKeyPrev = KEY_e;
        inKeyNext = KEY_f;
        inKeySel = KEY_g;
        inKeyExit = KEY_h;
    }

    //pdebug(("--inSelectNode--"));
    //pdebug(("ppndSelectedNode = %X", ppndSelectedNode));
    //pdebug(("*ppndSelectedNode = %X", *ppndSelectedNode));
    //pdebug(("**ppndSelectedNode = %X", **ppndSelectedNode));

    pflRecordList = pliListOfChoices;

    if (pndCurrentNode == NULL_CH)
        pndCurrentNode = pndListStart((List *) pliListOfChoices);
    if (pndCurrentNode)
        do {
            pfnSelectedField = (FieldNode *) pndCurrentNode;
            // usha_R2, July 1- commented the following line and added the next line.
            // psrFieldDefinitionPtr = &pflFieldList->prlParentRecord->psrFieldDefinitionPtr[pfnSelectedField->inFieldIndex];
            //            psrFieldDefinitionPtr = &pflRecordList->psrFieldDefinitionPtr[pfnSelectedField->inFieldIndex];
            psrFieldDefinitionPtr = (FieldDefinition *) ((unsigned char *) pflRecordList->psrFieldDefinitionPtr + (pfnSelectedField->inFieldIndex * FieldDefSize));
            //pdebug (("Field Msg Idx = %d", psrFieldDefinitionPtr->inFieldName));
            //pdebug (("Field Editable = %d", psrFieldDefinitionPtr->fFieldEditable));
            (*pfnDisplayNode) (pliListOfChoices, (RecordNode *) pndCurrentNode);

            inKey = inWaitKey(inGetIdleTimeOut());

            if ((inKey == '*') || (inKey == inKeyPrev)) {
                if ((pndCurrentNode = pndPreviousNode(pndCurrentNode)) == NULL_CH) {
                    //pdebug (("pndPreviousNode=NULL"));
                    pndCurrentNode = pndListEnd((List *) pliListOfChoices);
                }
            } else if ((inKey == '#') || (inKey == inKeyNext)) {
                if ((pndCurrentNode = pndNextNode(pndCurrentNode)) == NULL_CH) {
                    //pdebug (("pndNextNode=NULL"));
                    pndCurrentNode = pndListStart((List *) pliListOfChoices);
                }
            } else if (inKey == inKeyExit) {
                inKey = KEY_BS;
                *ppndSelectedNode = NULL_CH;
                return(inKey);
            } else if ((inKey == KEY_CANCEL) || (inKey == KEY_BS)) // BJD: KEY_CLR -> KEY_CANCEL
            {
                *ppndSelectedNode = NULL_CH;
                return(inKey);
            } else if ((inKey == inKeySel) || (inKey == KEY_CR))
                inKey = KEY_CR;
            else
                vdBeep();
        } while (inKey != KEY_CR);

    *ppndSelectedNode = pndCurrentNode;

    return(inKey);
} /* End of inSelectNode () */

int inSelectEditNode(RecordList* pliListOfChoices,Node** ppndSelectedNode,PFVD_FL_FN pfnDisplayNode) {
    char szLineBuf[4][MESSAGE_SIZE + 1];

    Node* pndCurrentNode = *ppndSelectedNode;
    int inKey = 0;

    FieldList* pflFieldList;
    FieldNode* pfnSelectedField;
    FieldDefinition* psrFieldDefinitionPtr;
    long FieldDefSize = REC_SIZEOF(FieldDefinition);

    TRANSACTION_OBJECT* pobTran;

    int inKeyPrev = KEY_a;
    int inKeyNext = KEY_b;
    int inKeyExit = KEY_d;
    int inKeySel = KEY_c;

    if (obDisp.inTerminalType == TERMINAL_OMNI_3200) {
        inKeyPrev = KEY_e;
        inKeyNext = KEY_f;
        inKeyExit = KEY_h;
        inKeySel = KEY_g;
    }

    if ((pobTran = pstGet_pobTran()) == NULL_CH)
        return VS_ERR;

    //pdebug(("--inSelectNode--"));
    //pdebug(("ppndSelectedNode = %X", ppndSelectedNode));
    //pdebug(("*ppndSelectedNode = %X", *ppndSelectedNode));
    //pdebug(("**ppndSelectedNode = %X", **ppndSelectedNode));

    pflFieldList = (FieldList *) pliListOfChoices;

    if (pndCurrentNode == NULL_CH)
        pndCurrentNode = pndListStart((List *) pliListOfChoices);
    if (pndCurrentNode)
        do {
            VS_BOOL fAllBatchesEmpty,
            fTabBatchEmpty;

            /* 3200: parse keys, display in right window */
            vdLoad3200Opt(szLineBuf, O3200_TBL_EDIT_KEYS_MSG);
            vdCreateOptWin3200(szLineBuf);

            pfnSelectedField = (FieldNode *) pndCurrentNode;
            //            psrFieldDefinitionPtr = &pflFieldList->prlParentRecord->psrFieldDefinitionPtr[pfnSelectedField->inFieldIndex];
            psrFieldDefinitionPtr = (FieldDefinition *) ((unsigned char *) pflFieldList->prlParentRecord->psrFieldDefinitionPtr + (pfnSelectedField->inFieldIndex * FieldDefSize));
            //pdebug (("Field Msg Idx = %d", psrFieldDefinitionPtr->inFieldName));
            //pdebug (("Field Editable = %d", psrFieldDefinitionPtr->fFieldEditable));
            (*pfnDisplayNode) ((FieldList *) pliListOfChoices, (FieldNode *) pndCurrentNode);

            inKey = inWaitKey(inGetIdleTimeOut());

            fAllBatchesEmpty = fChkAllHostBatches(pobTran);
            fTabBatchEmpty = fOpenTabEmpty(pobTran);
            if ((inKey == '*') || (inKey == inKeyPrev)) {
                if ((pndCurrentNode = pndPreviousNode(pndCurrentNode)) == NULL_CH)
                    pndCurrentNode = pndListEnd((List *) pliListOfChoices);
            } else if ((inKey == '#') || (inKey == inKeyNext)) {
                if ((pndCurrentNode = pndNextNode(pndCurrentNode)) == NULL_CH)
                    pndCurrentNode = pndListStart((List *) pliListOfChoices);
            } else if (inKey == inKeyExit) {
                inKey = KEY_BS;
                *ppndSelectedNode = NULL_CH;
                return(inKey);
            } else if ((inKey == KEY_CANCEL) || (inKey == KEY_BS)) // BJD: KEY_CLR -> KEY_CANCEL
            {
                *ppndSelectedNode = NULL_CH;
                return(inKey);
            } else if ((inKey == inKeySel) || (inKey == KEY_CR)) {
                inKey = NULL_CH;
                /*
                 *      Field is NOT Editable
                 */
                if (!fGetMegaPassword() && psrFieldDefinitionPtr->fFieldEditable == 0) {
                    vdDisplayMessageFromFile(EDIT_NOT_ALLOWED21, WARNING_MSG);
                    vdClearNonTitleLines();
                }
                /*
                 *      Field is NOT Editable with Open Batch
                 */
                else if (!fGetMegaPassword() && !(fChkAllHostBatches(pobTran) == VS_TRUE /*&& fOpenTabEmpty(pobTran) == VS_TRUE*/) && psrFieldDefinitionPtr->fFieldEditOpenBatch == 0)
                                /*
                                else if ( !srTCTRec.fMegaPassword && psrFieldDefinitionPtr->fFieldEditOpenBatch == 0 &&
                                        !(fAllBatchesEmpty == VS_TRUE && fTabBatchEmpty == VS_TRUE) )
                                          */ {
                    vdDisplayMessageFromFile(EDIT_NOT_ALLOWED21, WARNING_MSG);
                    vdDisplayMessageFromFile(BATCH_NOT_EMPTY_ERR_MSG15, STATUS_MSG);
                    SVC_WAIT(1000);
                    vdClearNonTitleLines();
                }
                /*
                 *      Field is Editable under current conditions or Mega Password was entered.
                 */
                else
                    inKey = KEY_CR;
            } else
                vdBeep();
        } while (inKey != KEY_CR);

    *ppndSelectedNode = pndCurrentNode;

    return(inKey);
} /* End of inSelectEditNode () */


List* pliCreateList(long lnListSize) {
    List* pliNewList;

    //pdebug(("--pliCreateList--"));



    pliNewList = (List *) pchAlloc((unsigned) lnListSize);
    if (pliNewList)
        pliNewList->inListSig = LIST_SIGNATURE;



    return(pliNewList);
}

void vdDestroyListAndNodes(List* pliObsoleteList) {
    Node* pndNextVictimNode = (Node*) NULL;
    Node* pndObsoleteNode;

    /** /pdebug(("--vdDestroyListAndNodes--"));*/
    if (fValidList(pliObsoleteList)) {
        for (pndObsoleteNode = pliObsoleteList->pndHead; pndObsoleteNode; pndObsoleteNode = pndNextVictimNode)
            if (fValidNode(pndObsoleteNode)) {
                pndNextVictimNode = pndObsoleteNode->pndNextNode;
                vdDestroyNode(pndObsoleteNode);
            }
        vdFree((char *) pliObsoleteList);
    }
}

Node* pndListStart(List* pliList) {
    /** /pdebug(("--pndListStart--"));*/
    if (fValidList(pliList))
        return(pliList->pndHead);
    else
        return(NULL_CH);
}

Node* pndListEnd(List* pliList) {
    /** /pdebug(("--pndListEnd--"));*/
    if (fValidList(pliList))
        return(pliList->pndTail);
    else
        return(NULL_CH);
}

int inAddToListStart(List* pliTown,Node* pndNewKid) {
    int inResult = VS_FAILURE;

    /** /pdebug(("--inAddToListStart--"));*/

    if (fValidList(pliTown) && fValidNode(pndNewKid)) {
        pndNewKid->pndPreviousNode = NULL_CH;
        pndNewKid->pndNextNode = pliTown->pndHead;
        if (pndNewKid->pndNextNode)
            pndNewKid->pndNextNode->pndPreviousNode = pndNewKid;
        pliTown->pndHead = pndNewKid;
        // Usha_r2, July 2 - commented the following line
        // pliTown->pndTail = NULL;
        if (pliTown->pndTail == NULL)
            pliTown->pndTail = pndNewKid;
        inResult = VS_SUCCESS;
    }
    return(inResult);
}

int inAddToListEnd(List* pliTown,Node* pndNewKid) {
    int inResult = VS_FAILURE;

    /** /pdebug(("--inAddToListEnd--"));*/
    if (fValidList(pliTown) && fValidNode(pndNewKid)) {
        pndNewKid->pndNextNode = NULL_CH;
        pndNewKid->pndPreviousNode = pliTown->pndTail;
        if (pndNewKid->pndPreviousNode)
            pndNewKid->pndPreviousNode->pndNextNode = pndNewKid;
        pliTown->pndTail = pndNewKid;
        if (pliTown->pndHead == NULL_CH)
            pliTown->pndHead = pndNewKid;
        inResult = VS_SUCCESS;
    }
    return(inResult);
}

int inNumberOfNodes(List* pliList) {
    int inNodeCount = 0;
    Node* pndNodePtr;

    if (fValidList(pliList))
        for (pndNodePtr = pliList->pndHead; pndNodePtr; pndNodePtr = pndNodePtr->pndNextNode) {
            if (fValidNode(pndNodePtr))
                ++inNodeCount;
        }
    return(inNodeCount);
}

Node* pndCreateNode(long lnNodeSize) {
    Node* pndNewNode;

    /** /pdebug(("--pndCreateNode--"));*/

    pndNewNode = (Node *) pchAlloc((unsigned) lnNodeSize);
    if (pndNewNode)
        pndNewNode->inNodeSig = NODE_SIGNATURE;

    return(pndNewNode);
}

void vdDestroyNode(Node* pndObsoleteNode) {
    /** /pdebug(("--vdDestroyNode--"));*/

    if (fValidNode(pndObsoleteNode))
        vdFree((char *) pndObsoleteNode);
}

Node* pndPreviousNode(Node* pndCurrentNode) {
    /** /pdebug(("--pndPreviousNode--"));*/
    if (fValidNode(pndCurrentNode))
        return(pndCurrentNode->pndPreviousNode);
    else
        return(NULL_CH);
}

Node* pndNextNode(Node* pndCurrentNode) {
    /** /pdebug(("--pndNextNode--"));*/
    if (fValidNode(pndCurrentNode))
        return(pndCurrentNode->pndNextNode);
    else
        return(NULL_CH);
}

#undef VSLIST_C

